package config

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

// AllConfig 整合Config
type AllConfig struct {
	Server     Server
	DataSource DataSource
	Redis      Redis
	Log        Log
	Jwt        Jwt
	ShortLink  ShortLink `mapstructure:"short_link"`
}

type Server struct {
	Port  string
	Level string
}

type DataSource struct {
	Host     string
	Port     string
	UserName string
	Password string
	DBName   string `mapstructure:"db_name"`
	Config   string
}

func (d *DataSource) Dsn() string {
	return d.UserName + ":" + d.Password + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.DBName + "?" + d.Config
}

type Redis struct {
	Host     string
	Port     string
	Password string
	DataBase int `mapstructure:"data_base"`
}

type Log struct {
	Level    string
	FilePath string
}

type Jwt struct {
	Admin JwtOption
	User  JwtOption
}

type JwtOption struct {
	Secret string
	TTL    string
	Name   string
}
type Domain struct {
	Default string `mapstructure:"default"`
}

type ShortLink struct {
	Group  Group
	Domain Domain
}
type Group struct {
	MaxNum int `mapstructure:"max_num"`
}

func InitLoadConfig() *AllConfig {
	// 使用pflag库来读取命令行参数，用于指定环境，默认为"dev"
	pflag.Parse()

	config := viper.New()
	// 设置读取路径
	config.AddConfigPath("./config")
	// 设置读取文件名字
	config.SetConfigName("application-dev")
	// 设置读取文件类型
	config.SetConfigType("yaml")
	// 读取文件载体
	var configData *AllConfig
	// 读取配置文件
	err := config.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("Use Viper ReadInConfig Fatal error config err:%s \n", err))
	}
	// 查找对应配置文件
	err = config.Unmarshal(&configData)
	if err != nil {
		panic(fmt.Errorf("read config file to struct err: %s\n", err))
	}
	// 打印配置文件信息
	//fmt.Printf("配置文件信息：%+v", configData)
	configData.PrintConfig()
	return configData

}

func (conf AllConfig) PrintConfig() {
	fmt.Println("==========配置文件信息==========")
	printStruct(reflect.ValueOf(conf), 0)
	fmt.Println("==============================")
}

// 递归打印结构体（核心逻辑）
func printStruct(v reflect.Value, indentLevel int) {
	// 处理指针类型
	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			fmt.Printf("%s<nil>\n", strings.Repeat("  ", indentLevel))
			return
		}
		v = v.Elem()
	}

	t := v.Type()
	indent := strings.Repeat("  ", indentLevel)

	// 打印结构体名称（顶层不显示类型名）
	if indentLevel > 0 {
		fmt.Printf("%s%s {\n", indent, t.Name())
	}

	// 遍历结构体字段
	for i := 0; i < v.NumField(); i++ {
		fieldVal := v.Field(i)
		fieldType := t.Field(i)
		fieldName := fieldType.Name

		// 字段缩进（比上级多2空格）
		fieldIndent := strings.Repeat("  ", indentLevel+1)
		fmt.Printf("%s%s: ", fieldIndent, fieldName)

		// 递归处理嵌套结构体
		if fieldVal.Kind() == reflect.Struct {
			fmt.Print("\n")
			printStruct(fieldVal, indentLevel+2)
			continue
		}

		// 敏感字段脱敏（根据字段名和值类型判断）
		if isSensitiveField(fieldName, fieldVal) {
			fmt.Printf("\"*****\"\n")
			continue
		}

		// 普通字段直接输出
		fmt.Printf("%v\n", fieldVal)
	}

	// 闭合结构体
	if indentLevel > 0 {
		fmt.Printf("%s}\n", indent)
	}
}

// 判断是否为敏感字段（按实际需求调整）
func isSensitiveField(name string, v reflect.Value) bool {
	sensitiveKeywords := []string{
		//"Password", "Secret", "Key", "Token", "AppId", "AccessKey",
	}

	// 检查字段名是否包含敏感词
	for _, kw := range sensitiveKeywords {
		if strings.Contains(name, kw) && v.Kind() == reflect.String && v.String() != "" {
			return true
		}
	}
	return false
}
